package com.Controller;

import cn.hutool.json.JSONUtil;
import com.POJO.Message;
import com.Service.MessageService;
import com.Service.WeiduService;
import com.Utils.JWTUtil;
import com.Utils.ServerEncoder;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@ServerEndpoint(value = "/websocket/{token}",encoders = { ServerEncoder.class })
@Controller // 此注解千万千万不要忘记，它的主要作用就是将这个监听器纳入到Spring容器中进行管理
public class WebSocketController {

    //静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;
    //concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。
    public static Map<String, WebSocketController> webSocketSet = new ConcurrentHashMap<>();

    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;

    private  static  MessageService messageService;
    @Autowired
    public void setUserService(MessageService messageService) {
        WebSocketController.messageService = messageService;
    }
    private  static WeiduService  weiduService;
    @Autowired
    public void setUserService(WeiduService  weiduService) {
        WebSocketController.weiduService = weiduService;
    }


    /**
     * 连接建立成功调用的方法*/
    @OnOpen
    public void onOpen(Session session, @PathParam("token") String token) {
        this.session = session;
        System.out.println(token);
        //获取当前用户账号信息
        DecodedJWT verify = JWTUtil.verifyToken(token);//验证令牌
        String tel=verify.getClaim("tel").asString();
        if(tel == null){
            tel=verify.getClaim("admin").asString();
        }
        System.out.println(tel);

        webSocketSet.put(tel,this);     //加入set中
        addOnlineCount();           //在线数加1
        log.info("用户"+tel+"加入！  当前在线人数为" + getOnlineCount());
//        try {
//            //系统消息推送所有在线用户给客户端
//            //封装系统推送消息,前端onmessage接收的数据
//            log.info("用户"+tel+"加入！  当前在线人数为" + getOnlineCount());
//            sendMessage("用户"+tel+"加入！  当前在线人数为" + getOnlineCount());
//        } catch (IOException e) {
//            log.error("websocket IO异常");
//        }
    }

    /**
     * 收到客户端消息后调用的方法
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println(message);
        //封装对象
        Message msg = JSONUtil.toBean(message, Message.class);
        System.out.println(msg);
        //封装时间
        msg.setTime(new Date());
        //发送的消息
        //String result=JSONUtil.toJsonStr(msg.getContent());
        //获取接收信息的用户
        String recipienttel = String.valueOf(msg.getRecipienttel());
        //String result = MessageUtils.formatMessage(msg);
        //发送消息
        if(webSocketSet.containsKey(recipienttel)){
            Session toSession = webSocketSet.get(recipienttel).getSession();
            log.info("toSession:" + toSession);
            sendMessage(toSession, msg);}
        else {
            System.out.println("用户不在线");
            weiduService.add(msg.getSendertel(),recipienttel,msg.getContent());
        }
        //将消息存储在数据库
        this.messageService.insert(msg);}

//群发消息
//        for (WebSocketServer item : webSocketSet) {
//            try {
//                item.sendMessage(message);
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        }



    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    /**
     * 发生错误
     * @param session 2
     * @param error 1
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        error.printStackTrace();
    }


    /**
     * 发送消息给单个用户
     *
     * @param message .
     */
    private void sendMessage(Session toSession, Message message) {
        try {
            toSession.getBasicRemote().sendObject(message);
        } catch (IOException | EncodeException e) {

            e.printStackTrace();
        }
    }
    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session, @PathParam("token") String token) {
        //从token获取用户数据
        DecodedJWT verify = JWTUtil.verifyToken(token);//验证令牌
        String tel=verify.getClaim("tel").asString();

        try {
            //广播
            log.info("有一连接关闭！当前在线人数为" + getOnlineCount());
            //从在线用户列表中移除
            webSocketSet.remove(tel,this);  //从set中删除
            subOnlineCount();           //在线数减1
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketController.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketController.onlineCount--;
    }

    public Session getSession() {
        return session;
    }
    /**
     * 给所有的客户端发送消息
     *
     * @param message 给客户端发送消息
     */
    private void sendMessageToAllUser(Message message) {
        //所有登录用户id
        Set<String> ids = webSocketSet.keySet();
        for (String tel : ids) {
            //发送消息
            Session toSession = webSocketSet.get(tel).getSession();
            sendMessage(toSession, message);
        }
    }

    /*
     * 群发自定义消息
     * */
//    public static void sendInfo(String message) throws IOException {
//        log.info(message);
//        for (WebSocketServer item : webSocketSet) {
//            try {
//                item.sendMessage(message);
//            } catch (IOException e) {
//                continue;
//            }
//        }
//    }
}
